#include <gpiod.h>
#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h> //ALSA头文件

snd_pcm_t* record_open(snd_pcm_uframes_t *period)
{
    snd_pcm_t* mic;
    // 打开录音设备，阻塞方式
    int error = snd_pcm_open(&mic, "hw:0,1", SND_PCM_STREAM_CAPTURE, 0);
    if (error)
    {
        fprintf(stderr, "snd_pcm_open: %s\n", snd_strerror(error));
        return NULL;
    }

    // 设置录音参数
    snd_pcm_hw_params_t *record_param;
    // 在栈上分配参数内存并初始化
    snd_pcm_hw_params_alloca(&record_param);
    error += snd_pcm_hw_params_any(mic, record_param);
    // 设置采样格式（有符号16位整数，小端序）
    error += snd_pcm_hw_params_set_format(mic, record_param, SND_PCM_FORMAT_S16_LE);
    // 设置访问方式（交错读写）
    error += snd_pcm_hw_params_set_access(mic, record_param, SND_PCM_ACCESS_RW_INTERLEAVED);
    // 设置采样频率（16KHz）
    error += snd_pcm_hw_params_set_rate(mic, record_param, 16000, 0);
    // 设置声道数量（单声道）
    error += snd_pcm_hw_params_set_channels(mic, record_param, 1);
    // 根据硬件参数配置声卡
    error = snd_pcm_hw_params(mic, record_param);
    if (error)
    {
        fprintf(stderr, "snd_pcm_hw_params: %s\n", snd_strerror(error));
        return NULL;
    }

    int dir = 0;
    error = snd_pcm_hw_params_get_period_size(record_param, period, &dir);
    if (error)
    {
        fprintf(stderr, "snd_pcm_hw_params_get_period_size: %s\n", snd_strerror(error));
        return NULL;
    }

    printf("period = %d frames\n", *period);

    return mic;
}

int record_close(snd_pcm_t *mic)
{
    // 关闭设备
    snd_pcm_close(mic);
}

int main(int argc, char **argv)
{
    struct gpiod_line *key1;
    struct gpiod_line_event event;
    struct gpiod_chip *gpiof = gpiod_chip_open_by_label("GPIOF");
    if (!gpiof)
    {
        perror("gpiod_chip_open");
        return EXIT_FAILURE;
    }

    key1 = gpiod_chip_get_line(gpiof, 9);
    if (!key1)
    {
        perror("gpiod_chip_get_line");
        gpiod_chip_close(gpiof);
        return EXIT_FAILURE;
    }

    if (gpiod_line_request_input(key1, "key") < 0)
    {
        perror("gpiod_line_request_both_edges_events");
        gpiod_line_release(key1);
        gpiod_chip_close(gpiof);
        return EXIT_FAILURE;
    }

    snd_pcm_uframes_t nframe;
    snd_pcm_t *mic = record_open(&nframe);
    if (!mic)
    {
        return EXIT_FAILURE;
    }

    char *buf = malloc(snd_pcm_frames_to_bytes(mic, nframe));
    if (!buf)
    {
        perror("malloc");
        return EXIT_FAILURE;
    }

    // 正在录音
    int recording = 0;
    int pressed = 0;

    FILE* fp = NULL;

    while (1)
    {
        if (recording)
        {
            snd_pcm_sframes_t rframe;
            // 从声卡中读取数据，写入缓冲区
            rframe = snd_pcm_readi(mic, buf, nframe);
            if (rframe < 0)
            {
                fprintf(stderr, "snd_pcm_readi: %s\n", snd_strerror(rframe));
                break;
            }

            //将音频数据写入文件
            fwrite(buf, snd_pcm_frames_to_bytes(mic, rframe), 1, fp);
        }

        //获取按键状态
        if (!pressed && (gpiod_line_get_value(key1) == 0))
        {
            puts("key1 pressed");
            // 启动录音
            snd_pcm_prepare(mic);
            fp = fopen(argv[1], "w+");
            if (!fp)
            {
                perror("fopen");
                break;
            }
            recording = 1;
            pressed = 1;
        }

        if (pressed && (gpiod_line_get_value(key1) == 1))
        {
            puts("key1 released");
            // 结束录音
            if (fp)
            {
                fclose(fp);
            }
            snd_pcm_drop(mic);
            recording = 0;
            pressed = 0;
        }
    }

    free(buf);

    record_close(mic);

    gpiod_line_release(key1);
    gpiod_chip_close(gpiof);

    return 0;
}